/**
 *  test_device.c - Test codes for device function and its functions.
 *                 It runs on Windows or Linux.
 *
 *  Copyright (C) 2008  ZhangHu
 *  All rights reserved.
 *  E-MAIL: anmnmnly@gmail.com
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
#include <stdlib.h>
#include <stdio.h>

#include "cunit/Automated.h"
#include "device_stubs.h"
#include "test_device.h"
#include "kernel/list.c"
#include "drivers/device.c"


device_init_func dev_init_func[DEVICE_NR] = {
    NULL, NULL
};



static void test_device_init_0(void) {
    int i;

    /* Tested function call */
    device_init();

    for(i=0; i<DEVICE_NR; i++) {
        CU_ASSERT_PTR_EQUAL(device_list[i].next, &device_list[i]);
        CU_ASSERT_PTR_EQUAL(device_list[i].prev, &device_list[i]);
    }
}



static void test_device_add_0(void) {
    /* Initializing argument 1 (pTask) */
    device_t *_Dev = NULL;

    /* Initializing argument 2 (pTask) */
    char_t *_Name = NULL;

    /* Initializing argument 3 (pTask) */
    char_t _Mid = 0;

    /* Initializing argument 4 (pTask) */
    char_t _Sid = 0;

    /* Tested function call */
    word_t _result = device_add(_Dev, _Name, _Mid, _Sid, NULL);

    CU_ASSERT_EQUAL(_result, DEV_FALSE);
}



static void test_device_add_1(void) {
    /* Initializing argument 1 (pTask) */
    struct _device __device= {0};
    device_t *_Dev = &__device;

    /* Initializing argument 2 (pTask) */
    char_t *_Name = NULL;

    /* Initializing argument 3 (pTask) */
    char_t _Mid = 0;

    /* Initializing argument 4 (pTask) */
    char_t _Sid = 0;

    /* Tested function call */
    word_t _result = device_add(_Dev, _Name, _Mid, _Sid, NULL);

    CU_ASSERT_EQUAL(_result, DEV_FALSE);
}



static void test_device_add_2(void) {
    word_t _result;

    /* Initializing argument 1 (pTask) */
    struct _device __device;
    device_t *_Dev = &__device;

    /* Initializing argument 2 (pTask) */
    char_t *_Name = "uart0";

    /* Initializing argument 3 (pTask) */
    char_t _Mid = DEVICE_NR;

    /* Initializing argument 4 (pTask) */
    char_t _Sid = 0;

    list_node_init(&_Dev->link);

    /* Tested function call */
    _result = device_add(_Dev, _Name, _Mid, _Sid, NULL);
    CU_ASSERT_EQUAL(_result, DEV_FALSE);
}



static struct _device __device;
static void test_device_add_3(void) {
    word_t _result;

    /* Initializing argument 1 (pTask) */
    device_t *_Dev = &__device;

    /* Initializing argument 2 (pTask) */
    char_t *_Name = "uart0";

    /* Initializing argument 3 (pTask) */
    char_t _Mid = 0;

    /* Initializing argument 4 (pTask) */
    char_t _Sid = 0;

    list_node_init(&_Dev->link);

    /* Tested function call */
    _result = device_add(_Dev, _Name, _Mid, _Sid, NULL);

    CU_ASSERT_EQUAL(_result, DEV_OK);
    CU_ASSERT_STRING_EQUAL(_Dev->name, _Name);
    CU_ASSERT_EQUAL(_Dev->mid, _Mid);
    CU_ASSERT_EQUAL(_Dev->sid, _Sid);
    CU_ASSERT_EQUAL(_Dev->used_cnt, 0);
    CU_ASSERT_EQUAL(_Dev->delete_flag, FALSE);
    CU_ASSERT_PTR_NULL(_Dev->release);
    CU_ASSERT_PTR_EQUAL(device_list[_Dev->mid].next, &_Dev->link);
    CU_ASSERT_PTR_EQUAL(device_list[_Dev->mid].prev, &_Dev->link);
    CU_ASSERT_PTR_EQUAL(_Dev->link.next, &_Dev->link);
    CU_ASSERT_PTR_EQUAL(_Dev->link.prev, &_Dev->link);
}



static void test_device_add_4(void) {
    word_t _result;

    /* Initializing argument 1 (pTask) */
    device_t *_Dev = &__device;

    /* Initializing argument 2 (pTask) */
    char_t *_Name = "uart0";

    /* Initializing argument 3 (pTask) */
    char_t _Mid = 0;

    /* Initializing argument 4 (pTask) */
    char_t _Sid = 0;

    list_node_init(&_Dev->link);

    /* Tested function call */
    _result = device_add(_Dev, _Name, _Mid, _Sid, NULL);

    CU_ASSERT_EQUAL(_result, DEV_FALSE);
}



static void test_device_add_5(void) {
    word_t _result;

    /* Initializing argument 1 (pTask) */
    device_t *_Dev = &__device;

    /* Initializing argument 2 (pTask) */
    char_t *_Name = "uart0";

    /* Initializing argument 3 (pTask) */
    char_t _Mid = 0;

    /* Initializing argument 4 (pTask) */
    char_t _Sid = 100;

    list_node_init(&_Dev->link);

    /* Tested function call */
    _result = device_add(_Dev, _Name, _Mid, _Sid, NULL);

    CU_ASSERT_EQUAL(_result, DEV_FALSE);

    /* Reset */
    device_init();
}



static void test_char_device_register_0(void) {
    /* Initializing argument 1 (pTask) */
    device_t *_Dev = NULL;

    /* Initializing argument 2 (pTask) */
    char_t *_Name = NULL;

    /* Initializing argument 3 (pTask) */
    char_t _Mid = 0;

    /* Initializing argument 4 (pTask) */
    char_t _Sid = 0;

    /* Tested function call */
    word_t _result = char_device_register(_Dev, _Name, _Mid, _Sid, NULL);

    CU_ASSERT_EQUAL(_result, DEV_FALSE);
}



static void test_char_device_register_1(void) {
    /* Initializing argument 1 (pTask) */
    struct _device __device= {0};
    device_t *_Dev = &__device;

    /* Initializing argument 2 (pTask) */
    char_t *_Name = NULL;

    /* Initializing argument 3 (pTask) */
    char_t _Mid = 0;

    /* Initializing argument 4 (pTask) */
    char_t _Sid = 0;

    /* Tested function call */
    word_t _result = char_device_register(_Dev, _Name, _Mid, _Sid, NULL);

    CU_ASSERT_EQUAL(_result, DEV_FALSE);
}



static void test_char_device_register_2(void) {
    word_t _result;

    /* Initializing argument 1 (pTask) */
    struct _device __device;
    device_t *_Dev = &__device;

    /* Initializing argument 2 (pTask) */
    char_t *_Name = "uart0";

    /* Initializing argument 3 (pTask) */
    char_t _Mid = DEVICE_NR;

    /* Initializing argument 4 (pTask) */
    char_t _Sid = 0;

    list_node_init(&_Dev->link);

    /* Tested function call */
    _result = char_device_register(_Dev, _Name, _Mid, _Sid, NULL);
    CU_ASSERT_EQUAL(_result, DEV_FALSE);
}



static void test_char_device_register_3(void) {
    word_t _result;

    /* Initializing argument 1 (pTask) */
    struct _device __device;
    device_t *_Dev = &__device;

    /* Initializing argument 2 (pTask) */
    char_t *_Name = "uart0";

    /* Initializing argument 3 (pTask) */
    char_t _Mid = 0;

    /* Initializing argument 4 (pTask) */
    char_t _Sid = 0;

    list_node_init(&_Dev->link);

    /* Tested function call */
    _result = char_device_register(_Dev, _Name, _Mid, _Sid, NULL);

    CU_ASSERT_EQUAL(_result, DEV_OK);
    CU_ASSERT_EQUAL(_Dev->dev_type, CHDEV);

    CU_ASSERT_PTR_EQUAL(device_list[_Dev->mid].prev, &_Dev->link);
    CU_ASSERT_PTR_EQUAL(_Dev->link.next, &_Dev->link);
    CU_ASSERT_PTR_EQUAL(_Dev->link.prev, &_Dev->link);
}



static void test_char_device_register_4(void) {
    word_t _result;

    /* Initializing argument 1 (pTask) */
    struct _device __device;
    device_t *_Dev = &__device;

    /* Initializing argument 2 (pTask) */
    char_t *_Name = "uart0";

    /* Initializing argument 3 (pTask) */
    char_t _Mid = 0;

    /* Initializing argument 4 (pTask) */
    char_t _Sid = 0;

    list_node_init(&_Dev->link);

    /* Tested function call */
    _result = char_device_register(_Dev, _Name, _Mid, _Sid, NULL);

    CU_ASSERT_EQUAL(_result, DEV_FALSE);

    /* Reset */
    device_init();
}


static char_t release_count = 0;
static void dev_release(void) {
    release_count++;
}



static void test_device_delete_0(void) {
    device_t *_Dev = (device_t *)kmalloc(sizeof(device_t));
    list_node_init(&_Dev->link);
    device_add(_Dev, "device0", 0, 100, dev_release);
    _Dev->delete_flag = TRUE;

    _Dev = (device_t *)kmalloc(sizeof(device_t));
    list_node_init(&_Dev->link);

    device_add(_Dev, "device1", 0, 101, NULL);
    _Dev->delete_flag = TRUE;
    _Dev->used_cnt = 1;

    device_delete(DEVICE_NR, 100);
    device_delete(1, 100);

    device_delete(0, 100);
    device_delete(0, 101);

    CU_ASSERT_EQUAL(release_count, 1);
    CU_ASSERT_PTR_EQUAL(device_list[0].next, &_Dev->link);
    CU_ASSERT_PTR_EQUAL(device_list[0].prev, &_Dev->link);

    /* Reset */
    device_init();
}



static void test_device_open_0(void) {
    device_t *_Dev = (device_t *)kmalloc(sizeof(device_t));
    list_node_init(&_Dev->link);
    device_add(_Dev, "device0", 0, 100, dev_release);
    _Dev->delete_flag = TRUE;
    _Dev->used_cnt = 1;

    _Dev = (device_t *)kmalloc(sizeof(device_t));
    list_node_init(&_Dev->link);
    device_add(_Dev, "device1", 0, 101, NULL);

    CU_ASSERT_PTR_NULL(device_open("device"));
    CU_ASSERT_PTR_NULL(device_open("device0"));
    CU_ASSERT_PTR_EQUAL(device_open("device1"), _Dev);

    /* Reset */
    device_init();
}



static void test_device_close_0(void) {
    device_t *pdev = NULL;
    list_t *plist = NULL;

    device_t *_Dev = (device_t *)kmalloc(sizeof(device_t));
    list_node_init(&_Dev->link);
    device_add(_Dev, "device0", 0, 100, dev_release);
    _Dev->delete_flag = TRUE;
    _Dev->used_cnt = 1;
    device_close(_Dev);
    CU_ASSERT_EQUAL(release_count, 2);

    _Dev = (device_t *)kmalloc(sizeof(device_t));
    list_node_init(&_Dev->link);
    device_add(_Dev, "device1", 0, 101, NULL);
    _Dev->delete_flag = FALSE;
    _Dev->used_cnt = 1;
    device_close(_Dev);

    _Dev = (device_t *)kmalloc(sizeof(device_t));
    list_node_init(&_Dev->link);
    device_add(_Dev, "device2", 0, 102, NULL);
    _Dev->delete_flag = TRUE;
    _Dev->used_cnt = 2;
    device_close(_Dev);

    device_close(NULL);

    plist = device_list[0].next;
    pdev = mac_find_entry(plist, device_t, link);
    CU_ASSERT_EQUAL(pdev->sid, 101);
    CU_ASSERT_EQUAL(pdev->used_cnt, 0);

    plist = plist->next;
    pdev = mac_find_entry(plist, device_t, link);
    CU_ASSERT_EQUAL(pdev->sid, 102);
    CU_ASSERT_EQUAL(pdev->used_cnt, 1);
}



int test_device_init(void) {
    printf("Device test ...\n\n");
    return(0);
}



int test_device_clean(void) {
    printf("Device test is over!\n\n");
    return(0);
}



CU_TestInfo test_device_cases[] = {
    {"test_device_init_0", test_device_init_0},
    {"test_device_add_0", test_device_add_0},
    {"test_device_add_1", test_device_add_1},
    {"test_device_add_2", test_device_add_2},
    {"test_device_add_3", test_device_add_3},
    {"test_device_add_4", test_device_add_4},
    {"test_device_add_5", test_device_add_5},
    {"test_char_device_register_0", test_char_device_register_0},
    {"test_char_device_register_1", test_char_device_register_1},
    {"test_char_device_register_2", test_char_device_register_2},
    {"test_char_device_register_3", test_char_device_register_3},
    {"test_char_device_register_4", test_char_device_register_4},
    {"test_device_delete_0", test_device_delete_0},
    {"test_device_open_0", test_device_open_0},
    {"test_device_close_0", test_device_close_0},
    CU_TEST_INFO_NULL
};

